﻿#ifndef SINGLETON_H
#define SINGLETON_H

#include <QMutex>
#include <QMutexLocker>
#include <QThread>
#include <QCoreApplication>
#include <QEventLoop>

class ThreadObject : public QObject
{
    Q_OBJECT
public:
    explicit ThreadObject(QObject *parent = nullptr) : QObject(parent) { }

signals:
    void threadStarted();
};

#define SINGLETON(x) \
public:\
    inline static x *instance()\
    {\
        static x *s_instance = nullptr;\
        static QMutex s_mutex;\
        if (s_instance == nullptr)\
        {\
            QMutexLocker locker(&s_mutex);\
            if (s_instance == nullptr)\
            {\
                s_instance = new x();\
            }\
        }\
        return s_instance;\
    }

#define SINGLETON_WITHIN_THREAD(x) \
public:\
    inline static x *instance()\
    {\
        static x *s_instance = nullptr;\
        static QMutex s_mutex;\
        if (s_instance == nullptr)\
        {\
            QMutexLocker locker(&s_mutex);\
            if (s_instance == nullptr)\
            {\
                s_instance = new x();\
                QEventLoop loop;\
                QThread *thread = new QThread();\
                s_instance->moveToThread(thread);\
                connect(thread, &QThread::started, s_instance, &x::threadStarted, Qt::QueuedConnection);\
                connect(thread, &QThread::finished, s_instance, &x::deleteLater, Qt::QueuedConnection);\
                connect(qApp, &QCoreApplication::aboutToQuit, thread, &QThread::quit, Qt::QueuedConnection);\
                connect(thread, &QThread::started, &loop, &QEventLoop::quit, Qt::QueuedConnection);\
                thread->start();\
                loop.exec();\
            }\
        }\
        return s_instance;\
    }

#endif // SINGLETON_H
